package com.zcs.app.base.mvvm

import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.os.Looper
import android.text.TextUtils
import android.util.Log
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.WindowManager
import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.ViewDataBinding
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.lifecycle.lifecycleScope
import com.tbruyelle.rxpermissions2.RxPermissions
import com.zcs.app.base.R
import com.zcs.app.base.asm.ActivityStackManger
import com.zcs.app.base.databinding.DialogCustomLoadingBinding
import com.zcs.app.base.dialog.CustomDialogCallbackAdapter
import com.zcs.app.base.dialog.CustomDialogHelper
import com.zcs.app.base.dialog.DialogParam
import com.zcs.app.base.dialog.NativeDialogCallback
import com.zcs.app.base.utils.KLogUtil
import com.zcs.app.base.utils.KeyboardUtil
import com.zcs.app.base.utils.ToastUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.lang.reflect.Method
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type

abstract class BaseKtActivity<T : ViewDataBinding, V : BaseViewModel> : AppCompatActivity() {
    // 这里保证不会在多线程调用rxPermissions，所以取消同步锁，减少消耗
    val rxPermissions by lazy(LazyThreadSafetyMode.NONE) {
        RxPermissions(this)
    }

    private var isLoading = false
    open fun isLazyInit(): Boolean = false
    private var isFullScreen = false
    private var progressDialog: AlertDialog? = null

    lateinit var mBinding: T
    lateinit var mViewModel: V

    override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
        if (ev.action == MotionEvent.ACTION_UP) {
            // ScreenSaverHelper.getInstance().updateLastUpTime()
        } else if (ev.action == MotionEvent.ACTION_DOWN) { //优化界面输入框 隐藏体验
            // get current focus,Generally it is EditText
            val view = currentFocus
            if (KeyboardUtil.isShouldHideSoftKeyBoard(view, ev)) {
                KeyboardUtil.hideSoft(this)
            }
        }
        return try {
            super.dispatchTouchEvent(ev)
        } catch (e: Exception) {
            false
        }
    }

    open fun needViewModel(): Boolean = true

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        ActivityStackManger.addActivity(this)
        // 初始化ViewDataBinding
        initViewDataBinding()
        // 关联生命周期
        mBinding.lifecycleOwner = this
        // 设置布局文件
        setContentView(mBinding.root)
        // 初始化ViewModel
        if (needViewModel())
            initViewModel()
        // 程序初始化-入口
        onReady()
        if (isLazyInit()) {
            showLoading()
            lifecycleScope.launch {
                delay(500)
                withContext(Dispatchers.Main) {
                    if (!isFinishing) {
                        onInit()
                        addOnClickListener()
                        hideLoading()
                    }
                }
            }
        } else {
            onInit()
            addOnClickListener()
        }
    }

    /**
     * 根据设置的类的泛型参数通过反射方式实例化ViewDataBinding对象
     */
    private fun initViewDataBinding() {
        val vbClass: Class<T> = getVMClass(this.javaClass, 0) as Class<T>
        try {
            val method: Method = vbClass.getMethod("inflate", LayoutInflater::class.java)
            mBinding = method.invoke(null, layoutInflater) as T
        } catch (e: Exception) {
            KLogUtil.e(Log.getStackTraceString(e))
        }
    }

    /**
     * 获取对应class类设置的第1个泛型参数对应的Class
     * @param clazz
     * @param actualTypeIndex 泛型參數索引位置
     * @return
     */
    private fun getVMClass(clazz: Class<*>, actualTypeIndex: Int): Type {
        val superClazz = clazz.genericSuperclass
        if (superClazz !is ParameterizedType) {
            throw RuntimeException("请设置类泛型")
        }
        return superClazz.actualTypeArguments[actualTypeIndex]
    }

    /**
     * 实例化ViewModel
     */
    private fun initViewModel() {
        val vmClass: Class<V> = getVMClass(this.javaClass, 1) as Class<V>
        // viewModel = ViewModelProvider(this).get(vmClass)
        mViewModel = ViewModelProviders.of(this).get(vmClass)
        registerBaseObserver()
    }

    /**
     * 初始化ViewModel
     */
    private fun registerBaseObserver() {
        mViewModel.showLoadingObserver.observe(this, Observer {
            if (it.isEmpty() || isFinishing) return@Observer
            if (it == BaseViewModel.TAG_HIDE_LOADING) {
                hideLoading()
            } else {
                showLoading(it)
            }
        })
        mViewModel.showToastObserver.observe(this, Observer {
            if (it.isEmpty() || isFinishing) return@Observer
            showToast(it)
        })
        mViewModel.showMessageObserver.observe(this, Observer {
            if (it.isEmpty() || isFinishing) return@Observer
            showMessage(it)
        })
    }

    open fun useEventBus() = false

    fun showLoading() {
        if (isFinishing) return
        showLoading("数据加载中...")
    }

    fun hideLoading() {
        if (isFinishing) return
        isLoading = false
        progressDialog?.dismiss()
        if (isFullScreen) requestFullScreen(null)
    }

    fun showErrorDialog(msg: String, title: String = "网络错误") {
        showMessage(msg)
        hideLoading()
    }

    fun showMessage(message: String?) {
        if (isFinishing) return
        hideLoading()
        if (!isFinishing) CustomDialogHelper.showCustomMessageDialog(this, message)
    }

    open fun showExitMessageDialog(msg: String?) {
        if (isFinishing || msg.isNullOrEmpty()) return
        hideLoading()
        val dialogParam = DialogParam()
        dialogParam.message = msg
        dialogParam.positiveBtnText = "退出"
        CustomDialogHelper.showCustomMessageDialog(
            this,
            dialogParam,
            object : CustomDialogCallbackAdapter() {
                override fun onConfirm() {
                    killMyself()
                }
            })
    }

    fun launchActivity(intent: Intent?) {
        startActivity(intent)
    }

    fun launchActivity(clz: Class<*>?) {
        launchActivity(Intent(this, clz))
    }

    fun showLoading(msg: String?) {
        // 显示Loading框
        if (!isFinishing) {
            if (Looper.myLooper() != Looper.getMainLooper()) {
                runOnUiThread { forceShowLoading(msg) }
            } else {
                forceShowLoading(msg)
            }
        }
    }

    protected open fun getDataFromNet() {}

    private fun forceShowLoading(msg: String?) {
        if (isFinishing) return
        if (progressDialog == null) {
            val binding = DialogCustomLoadingBinding.inflate(layoutInflater)
            val view = binding.root
            binding.tvTips.text = msg

            // progressDialog = new Dialog(this, R.style.CustomDialogWithDim);
            val builder = AlertDialog.Builder(this, R.style.CustomDialogFullScreen)
            builder.setView(view).setCancelable(false)
            try {
                progressDialog = builder.show()
                progressDialog?.setCanceledOnTouchOutside(false)
            } catch (e: java.lang.Exception) {
                e.printStackTrace()
            }
        } else {
            val tips = progressDialog?.findViewById<TextView>(R.id.tvTips)
            if (tips != null) tips.text = msg
        }
        if (!progressDialog?.isShowing!!) {
            if (!isFinishing) progressDialog?.show()
        }
    }

    fun showToast(message: String?) {
        if (isFinishing) return
        if (TextUtils.isEmpty(message)) return
        ToastUtils.showLong(message)
    }

    fun hideSoftInput() {}

    fun killMyself() {
        ActivityStackManger.finishActivity(this)
        finish()
    }

    override fun onDestroy() {
        hideLoading()
        CustomDialogHelper.dismissDialog(progressDialog)
        progressDialog = null
        super.onDestroy()
        ActivityStackManger.removeActivity(this)
    }

    /**
     * 移除全屏
     */
    protected open fun removeFullScreen() {
        isFullScreen = false
        val decorView = window.decorView
        decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE
    }

    /**
     * 全屏
     */
    protected open fun requestFullScreen(keepScreenOn: Boolean?) {
        isFullScreen = true
        val decorView = window.decorView
        decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_FULLSCREEN
                or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
        // 设置常亮
        if (keepScreenOn != null && keepScreenOn) setKeepScreenOn()
    }

    /**
     * 清除常亮
     */
    protected open fun clearKeepScreenOn() {
        try {
            window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
        }
    }

    /**
     * 设置屏幕常亮
     */
    protected open fun setKeepScreenOn() {
        KLogUtil.d("setKeepScreenOn() called")
        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
    }

    protected val mAppName: String by lazy(LazyThreadSafetyMode.NONE) {
        getString(R.string.app_name)
    }

    // 从设置页面回来后，是否检测权限
    protected var autoCheckPermission = false

    /**
     * 默认是退出APP
     */
    @Deprecated("use onNeverAsk instead", ReplaceWith("onDenied(permissionName, true)"))
    fun onDenied(permissionName: String) {
        onDenied(permissionName, true)
    }

    @Deprecated("use onNeverAsk instead")
    fun onDenied(permissionName: String, withExit: Boolean) {
        val dialogParam = DialogParam()
        dialogParam.title = "授权被拒绝"
        dialogParam.message = "为保证${mAppName}的正常使用，请为${mAppName}授予[${permissionName}]权限。"
        dialogParam.positiveBtnText = "重新授权"
        dialogParam.negativeBtnText = if (withExit) "退出" else "取消"
        CustomDialogHelper.showCustomConfirmDialog(this, dialogParam,
            object : NativeDialogCallback {
                override fun onConfirm() {
                    onInit()
                }

                override fun onCancel() {
                    if (withExit)
                        onBackPressed()
                }
            })
    }

    /**
     * 1.默认是退出APP
     * 2.默认自动重新检测
     */
    fun onNeverAsk(permissionName: String) {
        onNeverAsk(permissionName, withExit = true, autoCheckOnResume = true)
    }

    /**
     * 拒绝授权并不再提示
     * @param permissionName    权限中文名称
     * @param withExit          如果拒绝，是否退出APP
     * @param autoCheckOnResume 用户进入应用设置返回后，是否自动检测授权状态
     */
    fun onNeverAsk(permissionName: String, withExit: Boolean, autoCheckOnResume: Boolean) {
        // 申请权限时被拒绝了，并且不再询问。
        val dialogParam = DialogParam()
        dialogParam.title = "授权被拒绝"
        dialogParam.message = "为保证${mAppName}的正常使用，请在应用设置中为${mAppName}授予[${permissionName}]权限。"
        dialogParam.positiveBtnText = "应用设置"
        dialogParam.negativeBtnText = if (withExit) "退出" else "取消"
        CustomDialogHelper.showCustomConfirmDialog(this, dialogParam,
            object : NativeDialogCallback {
                override fun onConfirm() {
                    openAppDetailSettings(autoCheckOnResume)
                }

                override fun onCancel() {
                    if (withExit)
                        onBackPressed()
                }
            })
    }

    fun showPermissionTips(permissionName: String) {
        showToast("为保证${mAppName}的正常使用，请在应用设置中为${mAppName}授予[${permissionName}]权限。")
    }

    override fun onResume() {
        super.onResume()
        if (autoCheckPermission) {
            lifecycleScope.launch {
                delay(1000)
                withContext(Dispatchers.Main) {
                    if (!isFinishing) {
                        onInit()
                    }
                }
                autoCheckPermission = false
            }
        }
    }

    /**
     * 打开应用程序设置界面
     */
    protected open fun openAppDetailSettings() {
        openAppDetailSettings(true)
    }

    /**
     * @param checkPermissionOnResume 授权回来后是否自动检测授权状态
     */
    protected open fun openAppDetailSettings(checkPermissionOnResume: Boolean) {
        autoCheckPermission = checkPermissionOnResume
        try {
            val intent = Intent()
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            intent.action = "android.settings.APPLICATION_DETAILS_SETTINGS"
            intent.data = Uri.fromParts("package", packageName, null)
            startActivity(intent)
        } catch (e: Exception) {
            showMessage(e.message)
        }
    }

    /**
     * 初始化方法，如果有RxPermission权限申请，必须在这个方法内执行
     */
    abstract fun onInit()

    abstract fun initObserve()

    abstract fun initView()

    open fun initData() {}

    open fun addOnClickListener() {}

    // 用于懒加载的Activity提前初始化，在onInit之前执行
    open fun onReady() {}
}